home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Gold Collection
/
Software Vault - The Gold Collection (American Databankers) (1993).ISO
/
cdr35
/
dwnsrs57.zip
/
DOWNCOL.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-06-18
|
51KB
|
1,032 lines
/* ============================================================ */
/* Rob Hamerling's MAXIMUS download file scan and sort utility. */
/* -> DOWNCOL.C */
/* -> Functions to collect download file information. */
/* ============================================================= */
/* #define __DEBUG__ */
#define INCL_DOS
#define INCL_DOSFILEMGR
#define INCL_DOSERRORS
#define INCL_NOPMAPI
#include <os2.h>
#include <conio.h>
#include <fcntl.h>
#include <io.h>
#include <malloc.h>
#include <share.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys\types.h>
#include "..\max\mstruct.h" /* MAXIMUS definitions */
#include "downsort.h" /* downsort defines */
#include "downfpro.h" /* downsort function prototypes */
/* prototypes of local function functions */
void add_to_chain(FILECHAIN **cp, FILECHAIN *tp);
int area_selection(char *, char [][MAXANAME]);
FILECHAIN *add_comment(char *, DOWNPATH _HUGE *,
char *, short int, unsigned short int);
void add_pathspec(char *, FILECHAIN *);
FILECHAIN *assign_desc(short int, char *, FILECHAIN **,
DOWNPATH _HUGE *, char *, short int, USHORT);
char *build_desc(FILE *, char *, char **);
USHORT combine_comments(void);
FILECHAIN *desc_dup(FILECHAIN *, char *,
DOWNPATH _HUGE *, short int, USHORT, USHORT, USHORT);
USHORT fill_chn(DOWNPATH _HUGE *, FILECHAIN **);
FILECHAIN *file_element(DOWNPATH _HUGE *,
#ifndef __32BIT__
FILEFINDBUF *);
#else
FILEFINDBUF3 *);
#endif
USHORT free_orphan(void);
USHORT get_desc(DOWNPATH _HUGE *, FILECHAIN **);
char *parse_fname(char *);
int sort_path(const void *, const void *);
int split_fname(char *);
/* ---------------------------- */
/* Collect download file area's */
/* ---------------------------- */
unsigned short int collect_area(DOWNPATH _HUGE **area)
{
#ifndef __32BIT__
FILESTATUS fs; /* file status buffer */
unsigned short int
#else
FILESTATUS3 fs; /* file status buffer */
unsigned long int
#endif
af, oaction; /* file handle, open_action */
int rc; /* returncode */
short int i,j,k,m; /* counters */
struct _area a; /* MAXIMUS (minimum) area struct.*/
DOWNPATH _HUGE *d; /* ptr to array with area-info */
rc = DosOpen(areadat_path, /* open 'carefully' */
&af, /* pointer to File Handle */
&oaction, /* pointer to action field */
0L, /* new filesize (N/A) */
FILE_NORMAL, /* attributes */
FILE_OPEN, /* open flags */
OPEN_ACCESS_READONLY | /* mode */
OPEN_SHARE_DENYWRITE,
0L); /* no EA's */
if (rc != NO_ERROR) { /* open error */
fprintf(stderr, MSG_OPI, areadat_path, rc);
DosExit(0, rc);
}
if (oaction != FILE_EXISTED) { /* not found */
fprintf(stderr, MSG_OPA, areadat_path, oaction);
DosExit(0, 5);
}
else {
if (oper_mode != QUIET)
fprintf(stdout, MSG_COA, areadat_path);
#ifndef __32BIT__
rc = DosQFileInfo(af, 1, &fs, sizeof(fs)); /* get info of AREA.DAT */
#else
rc = DosQueryFileInfo(af, 1, &fs, sizeof(fs)); /* get info AREA.DAT */
#endif
read(af,(char *)&a,sizeof(struct _area)); /* obtain first part */
m = 0; /* init participating file count */
if (a.id != AREA_id) { /* validate MAXIMUS format */
fprintf(stderr, MSG_MX1, areadat_path);
fprintf(stderr, MSG_MX2, PROGNAME,VERSION,SUBVERS,SUFFIX,MAX);
}
else { /* acceptable AREA.DAT */
k = (short int)(fs.cbFile / a.struct_len); /* # area's */
for (i=0; i<k; i++) { /* count area's with downloads */
lseek(af, i*(long)a.struct_len, SEEK_SET); /* locate to next */
read(af, (char *)&a, sizeof(struct _area));
if (a.filepath[0] != '\0' &&
a.filepath[0] != ' ' &&
a.filepriv <= ABS_MAX_priv && /* within report privilege */
area_selection(a.name, selected_area)) /* not excluded */
m++; /* participating filearea count */
}
if (m > 0) { /* any area's participating */
#ifndef __32BIT__
d = (DOWNPATH _HUGE *)halloc(m, sizeof(DOWNPATH));
#else
d = (DOWNPATH *)malloc(m * sizeof(DOWNPATH));
#endif
if (d == NULL) { /* memory not obtained? */
fprintf(stderr, MSG_MEM, PROGNAME);
DosExit(0, 6);
}
else { /* have memory for area-info */
*area = d; /* set return pointer */
for (i=m=0; i<k; i++) { /* all area's */
lseek(af, i*(long)a.struct_len, SEEK_SET); /* locate to next*/
read(af, (char *)&a, sizeof(struct _area));
if ( a.filepath[0] != '\0' && /* filename(?) */
a.filepath[0] != ' ' && /* filename(?) */
a.filepriv <= ABS_MAX_priv && /* within report privileg*/
area_selection(a.name, selected_area)) { /* selected */
d[m].priv = a.filepriv; /* download privilege */
strcpy(d[m].name, a.name); /* area name ... edit! */
d[m].anum = i; /* AREA.DAT seq. nbr */
d[m].file_count = 0; /* init file count */
d[m].byte_count = 0L; /* init byte count */
d[m].newest = NULL; /* pointer to newest file*/
strcpy(d[m].pname, a.filepath); /* download path */
j = strlen(d[m].pname);
if (j>0 && d[m].pname[j-1] != '\\')
d[m].pname[j] = '\\'; /* backslash if needed */
strcpy(d[m].filesbbs, a.filesbbs); /* files.bbs */
strcpy(d[m].adesc, a.fileinfo); /* filearea title */
++m; /* filearea index */
}
}
}
/* manipulate here area-names for 'intelligent' sorting */
max_aname = 0; /* init max areaname length */
for (i=0; i<m; i++) /* all collected area's */
max_aname = max(strlen(d[i].name), max_aname);
for (i=0; i<m; i++) { /* all collected area's */
sprintf(d[i].ename,
(d[i].name[0]<'0' || d[i].name[0]>'9') /* not num */
? "%-*.*s" : "%*.*s", /* left or right aligned */
max_aname, max_aname, d[i].name);
d[i].ename[max_aname] = '\0'; /* end of string */
j = k = max_aname-1; /* init offset values */
while (j>=0 && d[i].ename[j] == ' ') /* search last char */
j--;
if (j < k) { /* spaces found */
while (j>=0 &&
d[i].ename[j]>='0' &&
d[i].ename[j]<='9') {
d[i].ename[k--] = d[i].ename[j]; /* move */
d[i].ename[j--] = ' '; /* replace by blank */
}
}
}
#if defined(__DEBUG__)
dump_area_array(d,m,"check on ename editing");
#endif
}
}
DosClose(af); /* close area.dat-file */
return(m); /* report number downloadarea's */
}
}
/* ---------------------------- */
/* Collect all file information */
/* ---------------------------- */
unsigned int collect_file(unsigned int a,
DOWNPATH _HUGE *area)
{
unsigned short int i,k,l,fc,orphan_count; /* counters */
FILECHAIN *ca,*ce; /* ptrs to file info */
fc = orphan_count = 0; /* init file and orphan count */
if (oper_mode != QUIET)
fprintf(stdout, MSG_COF);
qsort(area, a, sizeof(DOWNPATH), sort_path);
/* WARNING: do no sort again in this array! */
for (i=0; i<a; i++) { /* all 'included' download areas */
if (oper_mode == VERBOSE)
fprintf(stdout, MSG_ARE, area[i].pname, area[i].name);
else if (oper_mode != QUIET)
fprintf(stdout, DOT);
fflush(stdout); /* show output */
if (i<1 || stricmp(area[i].pname, area[i-1].pname)) { /* pathnames */
if (lp[P_ORP].priv[0] > HIDDEN) /* orphan report not req'd */
orphan_count += free_orphan(); /* free orphans still in chain */
ca = NULL; /* for new directory */
k = fill_chn(&area[i], &ca); /* read directory */
/* returns #files + ptr to first */
fc += k; /* add to total */
if (ca!=NULL) { /* any files in group */
if ((ce = first_element) != NULL) { /* not empty chain */
while (ce->next_element != NULL) /* find last element */
ce = ce->next_element;
ce->next_element = ca; /* couple new group to chain */
}
if (first_element==NULL) /* first non-empty group */
first_element = ca; /* set pointer to head of chain */
}
}
if (oper_mode==VERBOSE)
fprintf(stdout, " %5d\n",k); /* total this download path */
l = get_desc(&area[i], &ca); /* obtain descriptions */
if (oper_mode==VERBOSE && l>0) { /* any offline files found */
fprintf(stdout, MSG_ARE, area[i].pname, area[i].name);
fprintf(stdout, " %5d\n", k += l); /* value after get_desc */
}
fc += l; /* add 'extra' filecount */
if (first_element==NULL) /* very first */
first_element = ca; /* set pointer to head of chain */
} /* all area's processed */
if ((ca = first_element) != NULL) { /* any files */
if (lp[P_ORP].priv[0] > HIDDEN) { /* orphan report not req'd */
orphan_count += free_orphan(); /* free any left orphans */
if (ca->priv >= HIDDEN) { /* first is an orphan */
first_element=ca->next_element; /* new ptr to first */
free(ca); /* free memory block */
++orphan_count; /* one more dropped */
}
}
}
if (oper_mode==VERBOSE && orphan_count>0)
fprintf(stdout, MSG_ORP, orphan_count);
else if (oper_mode!=QUIET)
fprintf(stdout,"\n"); /* newline..flush */
fc -= orphan_count; /* less dropped orphans */
#if defined(__DEBUG__)
dump_file_chain(first_element, " --> after all areas");
#endif
if (fc) { /* file(s) present */
k=0; /* init count */
if ((ca = first_element) != NULL) { /* pointer to first element */
++k; /* at least 1 */
while (ca->next_element != NULL) { /* find last */
++k; /* another element */
ca = ca->next_element; /* pointer to next */
}
}
if (fc != k) { /* compare counts */
fprintf(stderr, MSG_IEC, fc, k); /* counter values */
DosExit(0, 99); /* quit on error */
}
}
return(fc); /* file total count */
}
/* ---------------------------------------- */
/* Add all subdir-filenames to the chain, */
/* for further processing by mainline. */
/* NOTE: - full path name assumed! */
/* returns number of files in this area */
/* ---------------------------------------- */
unsigned short int fill_chn(DOWNPATH _HUGE *parea,
FILECHAIN **cp)
{
int rc; /* returncode of DOS-calls */
unsigned short int fc; /* area-file counter */
FILECHAIN *ca,*ce,*tp; /* new, curr, temp, chain ptrs */
char down_spec[MAXPATH]; /* file specification buffer */
HDIR fhandle = HDIR_CREATE; /* FindFirst/Last handle */
#ifndef __32BIT__
FILEFINDBUF cf; /* file-info buffer */
unsigned int fentries; /* # entries to be retrieved */
#else
FILEFINDBUF3 cf; /* file-info buffer */
unsigned long int fentries; /* # entries to be retrieved */
#endif
fc = 0; /* init filecount of this area */
fentries = 1; /* retreive 1 at a time (DOS!) */
strcpy(down_spec,parea->pname); /* path */
strcat(down_spec, "*.*"); /* file-spec */
rc = DosFindFirst(down_spec,
&fhandle,
FILE_NORMAL,
&cf,
sizeof(cf),
&fentries,
#ifndef __32BIT__
0L); /* unused with OS/2 < 2.0 */
#else
FILE_ARCHIVED || FILE_READONLY); /* */
#endif
ca = NULL; /* no first in group yet */
while (rc == 0) {
if ((wild_comp(cf.achName,"FILES.*") != 0) &&
(wild_comp(cf.achName,"*.BAK") != 0) &&
(wild_comp(cf.achName,"SYSTEM*.?BS") != 0) &&
(wild_comp(cf.achName,"DIR.?BS") != 0)) {
tp = file_element(parea, &cf); /* add new element to chain */
/* note: exits if no memory */
if (ca == NULL) /* it is first element in group */
ca = ce = tp; /* first and last in group */
else { /* not first */
ce->next_element = tp; /* chain-ptr in previous */
ce = tp; /* new last in group */
}
++fc; /* update filecount this area */
byte_count += cf.cbFile; /* update file bytecount */
if (oper_mode==VERBOSE && (fc%25)==0) { /* every 25 files */
fprintf(stdout, " %5u\r", fc);
fflush(stdout);
}
}
fentries = 1; /* retreive 1 at a time (DOS!) */
rc = DosFindNext(fhandle,
&cf,
sizeof(cf),
&fentries);
}
DosFindClose(fhandle); /* close directory association */
*cp = ca; /* pointer to first new this area*/
return(fc);
} /* return # of allocated elements*/
/* -------------------------------------- */
/* Add file description to chain elements */
/* -------------------------------------- */
unsigned short int get_desc(DOWNPATH _HUGE *parea,
FILECHAIN **cp)
{
#ifndef __32BIT__
unsigned short int
#else
unsigned long int
#endif
fih, /* file handle */
oaction; /* open-action flags */
FILE *fi; /* file pointer */
unsigned short int y; /* number of offline files */
FILECHAIN *ce, *tp; /* ptrs to file-info */
char buf[MAXRCD]; /* read-buffer for FILES.BBS */
char filename[MAXFN]; /* filename from FILES.BBS buf */
char *desc, *rp; /* ptr to desc / return string */
short int i,k,m,p,x; /* counters */
short int fpriv; /* file privilege */
int rc; /* returncode */
int fn_off; /* filename offset */
unsigned short int bbsseq; /* current line number FILES.BBS */
char desc_spec[MAXPATH];
FILECHAIN **fa; /* pointer to file sort-array */
static char prop[4] = "/|\\-"; /* rotating propeller */
if (strlen(parea->filesbbs) > 0) /* explicit specification? */
strcpy(desc_spec,parea->filesbbs); /* explicitly specified FileList */
else { /* no */
strcpy(desc_spec,parea->pname); /* get path to download directory*/
strcat(desc_spec,lp[P_FIL].name); /* add filename */
strcat(desc_spec,"."); /* add separator */
strcat(desc_spec,lp[P_FIL].ext); /* add extension */
}
fpriv = parea->priv; /* area-priv is default file priv*/
/* FILES.BBS may be in use!!! */
rc = DosOpen(desc_spec, /* Open 'carefully' */
&fih, /* pointer to File Handle */
&oaction, /* pointer to action field */
0L, /* new filesize (N/A) */
FILE_NORMAL, /* attributes */
FILE_OPEN, /* open flags */
OPEN_ACCESS_READONLY | /* mode */
OPEN_SHARE_DENYWRITE,
0L); /* no EA's OS/2 2.0+ */
if (rc) { /* open error */
fprintf(stderr, MSG_OPI, desc_spec, rc);
return(0); /* no: return to caller */
}
if ((fi = fdopen(fih, "r")) == NULL) {
fprintf(stderr, MSG_OPA, desc_spec, -1); /* dummy rc */
return(0); /* no: return to caller */
}
ce = *cp; /* ptr to 1st element of group */
for (x=0; ce != NULL; x++) /* count collected dir entries */
ce = ce->next_element; /* pointer to next file entry */
if (x > 0) { /* if any files in dir */
fa = (FILECHAIN **)malloc(x * sizeof(FILECHAIN *));
if (fa == NULL) { /* not enough memory */
fprintf(stderr, MSG_MEM,PROGNAME);
DosExit(0, 11);
}
ce = *cp; /* ptr to 1st element of group */
for (i=0; ce != NULL; i++) { /* init sort array */
fa[i] = ce; /* element pointer into array */
ce = ce->next_element; /* pointer to next file entry */
}
qsort(fa, x, sizeof(FILECHAIN *), sort_gbl);
}
else /* no files in group */
fa=NULL; /* no array allocated */
y = 0; /* init 'offline' counter */
bbsseq = 0; /* init counter */
rp = fgets(buf, MAXRCD, fi); /* get first FILES.BBS record */
while (rp != NULL) { /* until end of FILES.BBS */
bbsseq++; /* line counter */
m = strlen(buf); /* length of input string */
if (m>1 && buf[0] == '\20') { /* privilege change (^P) ? */
for (k=0; k<HIDDEN-TWIT && priv_name[k][0]!=buf[1]; k++);
if (TWIT + k > parea->priv) /* only if higher than area-priv */
fpriv = TWIT + k; /* new (higher) prilivege */
rp = fgets(buf, MAXRCD, fi); /* continue */
}
else if (parse_fname(buf) == NULL) { /* NOT likely a filename */
if ( strncmp(buf, FILPREFX, 3)==0 || /* Downsort header line */
bbsseq <= 8 ) { /* first 8 lines */
} /* just skip these */
else if (lp[P_ALL].sortflag == KEEPSEQ || /* ALL-list with /K */
lp[P_IPF].sortflag == KEEPSEQ || /* IPF-list with /K */
lp[P_IP2].sortflag == KEEPSEQ || /* IP2-list with /K */
(lp[P_FIL].sortflag == KEEPSEQ && /* FIL-list */
lp[P_FIL].priv[0] <= HIDDEN)) { /* with '/K' */
tp = add_comment(EMPTY, parea, /* filename = null-string */
buf, fpriv, bbsseq);
add_to_chain(cp, tp); /* add element to end-of-chain */
++y; /* add 1 to 'offline' filecount */
}
rp = fgets(buf, MAXRCD, fi); /* continue with next line */
}
else { /* probably file descr record */
fn_off = split_fname(buf); /* pathspec -> extra file */
for (i=fn_off; /* starting point of scan */
i < fn_off+MAXFN-1 && /* maximum filename length (8.3) */
i < m && /* string length */
buf[i] != ' ' && /* space character */
buf[i] != '\r' && /* CR character */
buf[i] != '\n'; /* LF character */
i++); /* scan for filespec */
strncpy(filename, buf+fn_off, i-fn_off); /* select filename */
filename[i - fn_off] = '\0'; /* end of string */
strupr(filename); /* filename in capitals */
desc = build_desc(fi, buf, &rp); /* build description string */
if (desc == NULL) /* no description */
rp = fgets(buf, MAXRCD, fi); /* prepare for next file entry */
tp = assign_desc(x, filename, /* assign desc to file(s) */
fa, parea, desc, fpriv, bbsseq);
if (tp != NULL) { /* new element for group */
add_to_chain(cp, tp); /* add element to end-of-chain */
if (fn_off > 0) /* pathspec -> extra file */
add_pathspec(asciiz(buf), tp); /* add also file-info */
++y; /* add 1 to 'extra' filecount */
}
}
if (oper_mode == VERBOSE && (bbsseq%5) == 0) {
fprintf(stdout, "%c\r",prop[p=(++p)&3]); /* propeller */
fflush(stdout);
}
}
if (fa != NULL) /* memory for array allocated */
free(fa); /* free temp sort array */
x = combine_comments(); /* drop comment pairs */
if (oper_mode == VERBOSE)
fprintf(stdout, " \r"); /* clear propeller */
fclose(fi); /* finished with this FILES.BBS */
DosClose(fih); /* close the handle */
return(y-x); /* return 'offline' filecount */
/* (includes comment elements) */
}
/* -------------------------------------- */
/* Add a new file element to end-of-chain */
/* -------------------------------------- */
void add_to_chain(FILECHAIN **cp,
FILECHAIN *tp)
{
FILECHAIN *ce; /* work pointer */
if (*cp == NULL) { /* group was empty */
*cp = tp; /* return ptr to first in group */
if (first_element == NULL) /* whole chain empty */
return; /* ===> nothing else to do here! */
else /* something in chain */
ce = first_element; /* ptr to very 1st element */
}
else
ce = *cp; /* pointer to 1st in group */
while (ce->next_element != NULL) /* search last element */
ce = ce->next_element;
ce->next_element = tp; /* add new element to chain */
}
/* ------------------------------------- */
/* Build file description memory block */
/* ------------------------------------- */
char *build_desc(FILE *fi,
char *ibuf,
char **rp)
{
char *fd; /* pointer memory block with desc*/
char *desc; /* string work pointers */
char buf2[MAXDESC]; /* work buffers */
unsigned short int k; /* counter */
desc = next_word(ibuf); /* locate description */
if (desc != NULL) { /* start of description found */
for (k=0; desc[k]; ++k) { /* search first CR/LF */
if (desc[k]=='\r' || desc[k]=='\n') {
desc[k] = '\0';
break;
}
}
strcpy(buf2, desc); /* save desc in buf2 */
while (((*rp = fgets(ibuf, MAXDESC, fi)) != NULL) && /* next rcd */
(ibuf[0] == ' ') && /* probably desc continuation */
((desc = next_word(ibuf)) != NULL)) {
for (k=0; desc[k]!='\0'; ++k) {
if (desc[k]=='\r' || desc[k]=='\n') {
desc[k] = '\0';
break;
}
}
if ((strlen(buf2) + k + 1) <= sizeof(buf2)) { /* not too long */
strcat(buf2," "); /* single space */
strcat(buf2, desc); /* concat desc to buf2 */
}
}
fd = malloc(strlen(buf2)+1); /* obtain memory */
if (fd == NULL) {
fprintf(stderr, MSG_MEM, PROGNAME); /* not enough memory */
DosExit(0, 12);
}
else
strcpy(fd, buf2); /* store description */
}
else /* no description */
fd = NULL; /* return value */
return(fd); /* return with pointer */
}
/* ------------------------------------- */
/* Assign description to file element(s) */
/* ------------------------------------- */
FILECHAIN *assign_desc(short int x,
char *filename,
FILECHAIN **fa,
DOWNPATH _HUGE *parea,
char *desc,
short int fpriv,
unsigned short int bbsseq)
{
short int low,high,index; /* indexes */
short int b,n; /* counters */
unsigned short int dlb,dlt; /* download flags in description */
FILECHAIN *tp; /* ptr to file-info */
char dl_flags[5]; /* copy of first part description*/
dlb = dlt = 0; /* flags off */
while (desc != NULL) { /* only when real descr. present */
strncpy(dl_flags, desc, 4); /* copy part of description */
if (dl_flags[0] == '/') { /* could be valid dl_flag */
strupr(dl_flags); /* make all uppercase */
if (dl_flags[1] == 'B' || dl_flags[2] == 'B')
dlb = 1; /* unlimited download bytes flag */
if (dl_flags[1] == 'T' || dl_flags[2] == 'T')
dlt = 1; /* unlimited download time flag */
desc = next_word(desc); /* shift the description pointer */
}
else /* not MAXIMUS dl-flag */
break; /* escape from while-loop */
}
low = 0; /* index of first entry */
high = x-1; /* index of last entry */
while (low <= high) { /* binary search in array */
index = (high + low) / 2; /* middle of interval */
if ((b = wild_comp(fa[index]->fname,filename)) < 0)
low = index + 1; /* new low boundary */
else if (b > 0) /* 'b'-value from previous 'if' */
high = index - 1; /* new high boundary */
else
break; /* equal: found */
}
tp = NULL; /* init to 'not offline' */
if (x < 1 || /* no files in directory at all */
wild_comp(fa[index]->fname,filename)) { /* this one not in dir */
tp = file_element(parea, NULL); /* alloc new element */
strcpy(tp->fname, filename); /* copy filename to new element */
tp->fdesc = (desc != NULL) ? desc : NDS; /* assign 'some' desc */
tp->priv = fpriv; /* copy privilege */
tp->fseq = bbsseq; /* copy FILES.BBS line number */
tp->dl_b = dlb; /* copy download bytes flag */
tp->dl_t = dlt; /* copy download time flag */
if (oper_mode == VERBOSE)
fprintf(stdout," \t%s %s\n", OFFLINE, filename); /* filename */
}
else { /* file found in directory */
n = index; /* 'hit' and lower entries */
while (n>=0 && wild_comp(fa[n]->fname,filename) == 0) {
if (fa[n]->fdesc == NULL) { /* no description assigned yet */
fa[n]->fdesc = (desc==NULL) ? NDS : desc;
fa[n]->parea = parea; /* copy / overwrite area ptr */
fa[n]->priv = fpriv; /* copy privilege */
fa[n]->dl_b = dlb; /* copy download bytes flag */
fa[n]->dl_t = dlt; /* copy download time flag */
fa[n]->fseq = bbsseq; /* copy FILES.BBS line number */
}
else if (strcmp(fa[n]->parea->name,parea->name)) /* diff. dir */
tp = desc_dup(fa[n], desc, parea, fpriv, bbsseq, dlb, dlt); /*new*/
--n; /* next lower */
}
n = index + 1; /* higher entries */
while (n<x && wild_comp(fa[n]->fname,filename) == 0) {
if (fa[n]->fdesc == NULL) { /* no description assigned yet */
fa[n]->fdesc = (desc==NULL) ? NDS : desc;
fa[n]->parea = parea; /* copy / overwrite area ptr */
fa[n]->priv = fpriv; /* copy privilege */
fa[n]->dl_b = dlb; /* copy download bytes flag */
fa[n]->dl_t = dlt; /* copy download time flag */
fa[n]->fseq = bbsseq; /* copy FILES.BBS line number */
}
else if (strcmp(fa[n]->parea->name,parea->name)) /* diff. dir */
tp = desc_dup(fa[n], desc, parea, fpriv, bbsseq, dlb, dlt); /*new*/
++n; /* next higher */
}
}
return(tp); /* return pointer to new(?) */
/* element or NULL if not new */
}
/* ---------------------------------------------- */
/* Create duplicate file element with description */
/* ---------------------------------------------- */
FILECHAIN *desc_dup(FILECHAIN *fa,
char *desc,
DOWNPATH _HUGE *parea,
short int fpriv,
unsigned short int bbsseq,
unsigned short int dlb,
unsigned short int dlt)
{
FILECHAIN *tp; /* ptr to file-info */
tp = file_element(parea, NULL); /* alloc new element */
tp->wdate = fa->wdate; /* copy file wrtie date */
tp->wtime = fa->wtime; /* copy file write time */
tp->cdate = fa->cdate; /* copy file create date */
tp->ctime = fa->ctime; /* copy file create time */
tp->size = fa->size; /* copy file size */
tp->attr = fa->attr; /* copy file attr */
tp->fseq = bbsseq; /* copy FILES.BBS line number */
tp->priv = fpriv; /* copy privilege */
tp->dl_b = dlb; /* copy download bytes flag */
tp->dl_t = dlt; /* copy download time flag */
strcpy(tp->fname, fa->fname); /* copy filename to new element */
tp->fdesc = (desc != NULL) ? desc : NDS; /* add pointer to desc. */
return(tp); /* return pointer */
}
/* ---------------------------------------- */
/* Add single file-entry to file-chain */
/* returns: pointer to new element */
/* ---------------------------------------- */
FILECHAIN *file_element(DOWNPATH _HUGE *parea,
#ifndef __32BIT__
FILEFINDBUF *cf)
#else
FILEFINDBUF3 *cf)
#endif
{
FILECHAIN *tp; /* temporary-pointer */
tp = (FILECHAIN *)malloc(sizeof(FILECHAIN));
if (tp == NULL) {
fprintf(stderr, MSG_MEM, PROGNAME); /* not enough memory */
DosExit(0, 11);
}
memset(tp, '\0', sizeof(FILECHAIN)); /* whole struct zeroes */
tp->next_element = NULL; /* ptr to next */
tp->fseq = 65535; /* default FILES.BBS line number */
tp->priv = HIDDEN; /* unless FILES.BBS proves otherw*/
tp->fdesc = NULL; /* unless found in FILES.BBS */
tp->fpath = NULL; /* explicit path in FILES.BBS */
tp->parea = parea; /* copy pointer to area info */
if (cf != NULL) { /* file-system info available */
tp->wdate = cf->fdateLastWrite;
tp->wtime = cf->ftimeLastWrite;
if (file_time(cf->fdateCreation, cf->ftimeCreation) >
file_time(cf->fdateLastWrite, cf->ftimeLastWrite) ) { /* HPFS */
tp->cdate = cf->fdateCreation; /* creation most recent */
tp->ctime = cf->ftimeCreation;
}
else { /* otherwise and non-HPFS volumes*/
tp->cdate = cf->fdateLastWrite;
tp->ctime = cf->ftimeLastWrite;
}
tp->size = cf->cbFile;
tp->attr = cf->attrFile;
strncpy(tp->fname, cf->achName, MAXFN);
}
return(tp);
}
/* --------------------------------- */
/* Build comment entry in file-chain */
/* --------------------------------- */
FILECHAIN *add_comment(char *filename,
DOWNPATH _HUGE *parea,
char *fdesc,
short int fpriv,
unsigned short int bbsseq)
{
FILECHAIN *tp; /* ptr to file-info */
char *fd; /* ptr to file description */
char buf2[MAXDESC]; /* work buffer */
unsigned short int k; /* counter */
strncpy(buf2, fdesc, MAXDESC); /* save desc in buf2 */
for (k=0; buf2[k]!='\0'; ++k) /* scan work buffer */
if (buf2[k]=='\r' || buf2[k]=='\n') { /* for CR/LF */
buf2[k] = '\0'; /* replace by end-of-string */
break;
}
tp = file_element(parea, NULL); /* alloc new element */
strncpy(tp->fname, filename, MAXFN); /* EMPTY for comment */
tp->priv = fpriv; /* privilege */
tp->fseq = bbsseq; /* FILES.BBS line number */
tp->cmt = 1; /* indicate as comment element */
fd = malloc(k + 1); /* obtain memory for desc */
if (fd == NULL) {
fprintf(stderr, MSG_MEM, PROGNAME); /* not enough memory */
DosExit(0, 12);
}
else {
strcpy(fd, buf2); /* store description */
tp->fdesc = fd; /* pointer to desc */
}
return(tp); /* return pointer */
}
/* ------------------------------------------------------ */
/* supply file-entry with explicit path spec in FILES.BBS */
/* ------------------------------------------------------ */
void add_pathspec(char *filespec, /* asciiz filespec */
FILECHAIN *tp) /* pointer to file element */
{
#ifndef __32BIT__
FILESTATUS cf; /* file-info buffer */
#else
FILESTATUS3 cf; /* file-info buffer */
#endif
int fn_off; /* offset filename in filespec */
if
#ifndef __32BIT__
( DosQPathInfo(strupr(filespec), 1, (char *)&cf, sizeof(cf), 0L)
#else
( DosQueryPathInfo(strupr(filespec), 1, &cf, sizeof(cf))
#endif
!= 0) {
fprintf(stderr, "\tfile %s not found: %s\n", filespec);
return; /* return without info */
}
else {
fn_off = split_fname(filespec); /* path size */
strncpy(tp->fname, filespec+fn_off, MAXFN);
strupr(tp->fname); /* filename in capitals */
tp->fname[MAXFN-1] = '\0'; /* ensure string termination */
tp->fpath = malloc(fn_off + 1); /* mem for path */
if (tp->fpath != NULL) { /* memory obtained */
strncpy(tp->fpath, strupr(filespec), fn_off); /* copy path */
*(tp->fpath + fn_off) = '\0'; /* end of string */
}
tp->wdate = cf.fdateLastWrite;
tp->wtime = cf.ftimeLastWrite;
if (file_time(cf.fdateCreation, cf.ftimeCreation) >
file_time(cf.fdateLastWrite, cf.ftimeLastWrite) ) { /* HPFS */
tp->cdate = cf.fdateCreation; /* creation most recent */
tp->ctime = cf.ftimeCreation;
}
else { /* otherwise and non-HPFS volumes*/
tp->cdate = cf.fdateLastWrite;
tp->ctime = cf.ftimeLastWrite;
}
tp->size = cf.cbFile;
tp->attr = cf.attrFile;
return; /* back to caller */
}
}
/* ----------------------------------------------------------- */
/* Release memory occupied by orphan entries. */
/* If first element contains an orphan it will not be removed! */
/* ----------------------------------------------------------- */
unsigned short int free_orphan()
{
unsigned short int orp_cnt; /* removed orphan counter */
FILECHAIN *ca,*cb; /* current and next chain pointer*/
orp_cnt = 0; /* initial orphan count */
if ((ca=first_element) != NULL) { /* any file elements in chain */
while ((cb=ca->next_element) != NULL) { /* all elements (but first) */
if (cb->priv >= HIDDEN) { /* probably orphan? */
ca->next_element = cb->next_element; /* new ptr in current elemen*/
free(cb); /* free memory block */
++orp_cnt; /* one more dropped */
} /* note: do not shift current */
else /* not an orphan */
ca = cb; /* shift +1 current element */
}
} /* only orphans */
return(orp_cnt); /* report # of removed orphans */
}
/* ---------------------------------------------------- */
/* Combine consecutive comment lines to a single string */
/* return the number of freed chain elements */
/* ---------------------------------------------------- */
unsigned short int combine_comments(void)
{
unsigned short int cmt_cnt; /* freed elements count */
FILECHAIN *ca,*cb; /* current and next chain pointer*/
char *new; /* ptr to combined comments */
unsigned int k,l; /* string lengths */
#if defined(__DEBUG__)
dump_file_chain(first_element, "begin combine_comments()");
#endif
cmt_cnt = 0; /* initial freed elements count */
if ((ca=first_element) != NULL) { /* any elements in chain */
while ((cb=ca->next_element) != NULL) { /* all elements */
if (ca->fname[0] == '\0' && /* comment #1 */
cb->fname[0] == '\0' && /* comment #2 */
cb->fseq == ca->fseq+1) { /* consecutive lines in FILES.BBS*/
k = strlen(ca->fdesc); /* take length of 1st comment */
l = strlen(cb->fdesc); /* take length of 2nd comment */
if ((new = (char *)malloc(k+l+2)) != NULL) { /* mem obtained */
strcpy(new,ca->fdesc); /* copy 1st comment */
strcat(new,"\n"); /* insert newline */
strcat(new,cb->fdesc); /* copy 2nd comment */
free(ca->fdesc); /* release 1st old comment */
free(cb->fdesc); /* release 2nd old comment */
ca->fdesc = new; /* ptr to combined desc in cur el*/
ca->next_element = cb->next_element; /* new ptr in cur el. */
free(cb); /* release 2nd chain-element */
++cmt_cnt; /* update counter */
}
else
ca = cb; /* no memory: proceed */
}
else /* not 2 consecutive comments */
ca = cb; /* shift +1 current element */
}
} /* only orphans */
#if defined(__DEBUG__)
dump_file_chain(first_element, "end combine_comments()");
#endif
return(cmt_cnt); /* report # of removed elements */
}
/* ----------------------------------------- */
/* Check if string could be a filename */
/* Only needed as distiction form decription */
/* Returns NULL if probably not a filespec. */
/* ----------------------------------------- */
char *parse_fname(char *buf)
{
char c0; /* first character */
c0 = buf[0]; /* take first character on line */
if ( strlen(buf) < 2 || /* empty line */
c0 <= ' ' ||
c0 == '\"' ||
(c0 >= '+' && c0 <= '/') ||
(c0 >= ':' && c0 <= '>') ||
(c0 >= '[' && c0 <= ']') ||
c0 == '|' ||
c0 >= 128)
return(NULL); /* probably not a filename */
else /* now check for pathspec */
return(buf);
}
/* ----------------------------------- */
/* Split path (if any) from filespec. */
/* Returns offset to filename in buf. */
/* ----------------------------------- */
int split_fname(char *buf)
{
char *pFile; /* pointer */
char tempbuf[2048]; /* work buffer */
strcpy(tempbuf, asciiz(buf)); /* copy first 'word' */
pFile = strrchr(tempbuf,'\\'); /* search last backslash */
if (pFile == NULL) /* no directory spec found */
pFile = strrchr(tempbuf,':'); /* search last colon */
if (pFile == NULL) /* also no drive spec found */
return(0); /* zero: no explicit path spec'd */
else /* explicit pathspec found */
return(pFile - tempbuf + 1); /* offset to filename in buf */
}
/* ------------------------------------- */
/* Determine if area is within selection */
/* ------------------------------------- */
int area_selection(char *name,
char sel_array[][MAXANAME])
{
int result;
short int i;
if (area_IN_EX) { /* area selection specified */
result = (area_IN_EX < 0) ? 1 : 0; /* default not found: IN=0 EX=1 */
for (i=0; strcmp(sel_array[i], EMPTY); i++) {
if (!strnicmp(sel_array[i], name, strlen(sel_array[i]))) {
result = (area_IN_EX < 0) ? 0 : 1; /* found: IN=1 EX=0 */
break; /* escape from while-loop */
}
}
}
else
result = 1; /* no selections: all */
return(result); /* return selection result */
}
/* =================================================== */
/* Compare for sort of area-array on download pathname */
/* =================================================== */
int sort_path(const void *p,
const void *q)
{
int rc;
DOWNPATH _HUGE *x, *y;
x = (DOWNPATH _HUGE *)p;
y = (DOWNPATH _HUGE *)q;
if ((rc = stricmp(x->pname, y->pname)) == 0) /* download pathname */
rc = stricmp(x->name, y->name); /* area name */
return(rc);
}
#if defined(__DEBUG__)
/* =============== */
/* Dump area array */
/* =============== */
int dump_area_array(DOWNPATH _HUGE *aa, /* pointer to array */
short int m, /* number of elements */
char *id) /* log id */
{
short int i;
FILE *log;
log = fopen("downsort.log","a"); /* append! */
fprintf(log,"\n"); /* newline */
sep_line(log,'═',79); /* separate from previous append */
fprintf(log,"(%s) %s\n", today, id); /* timestamp + id */
flushall();
for (i=0; i<m; i++) {
fprintf(log,"\n%4d. bytecount=%10lu priv=%5d anum=%d filecount=%5u\n",
i+1,
aa[i].byte_count,
aa[i].priv,
aa[i].anum,
aa[i].file_count);
fprintf(log," name %s\nename %s\npname %s\nf_bbs %s\n desc %s\n",
aa[i].name,
aa[i].ename,
aa[i].pname,
aa[i].filesbbs,
aa[i].adesc);
fprintf(log,"newst %s\n",
(aa[i].newest != NULL) ? aa[i].newest->fname : "-");
flushall(); /* write buffers before continue */
}
fclose(log);
return(i);
}
/* =============== */
/* Dump file chain */
/* =============== */
int dump_file_chain(FILECHAIN *f, /* pointer to chain */
char *id) /* log id */
{
FILE *log;
unsigned short int fc; /* element count */
FILECHAIN *fe; /* */
log = fopen("downsort.log","a"); /* append! */
fprintf(log,"\n"); /* newline */
sep_line(log,'═',79,0); /* separate from previous append */
fprintf(log,"(%s) %s\n\n", today, id); /* timestamp + id */
flushall(); /* force physical write(s) */
fe = f; /* pointer to first element */
fc = 0; /* counter=0 */
while(fe != NULL) {
if (fe->fname[0] != '\0') {
fprintf(log,"%*.*s", MAXANAME, MAXANAME, fe->parea->name); /* area */
fprintf(log," %s ", fe->fname); /* filename */
}
fprintf(log,"%s\n",
(fe->fdesc != NULL) ? fe->fdesc : EMPTY); /* file desc */
fc++;
fe = fe->next_element;
}
fprintf(log,"\nChain_element_count = %u\n\n", fc);
fclose(log);
return(fc);
}
#endif